package UIFree.controls.FloatingArea
{
	import UIFree.controls.uif_arrowbutton;
	import UIFree.controls.uif_maskedArea;
	import UIFree.uif_component;
	import UIFree.uif_draw;
	import UIFree.uif_ecomponent;
	
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	public class uiff_frame extends uif_maskedArea {
		private var _area				: uiff_area;
		private var _inertia			: Point;
		private var _sr					: Point;
		private var _mousePrev			: Point;
		private var _buttonDown			: Boolean;
		private var _buttons			: Array;
		private var _buttonsLayer		: uif_ecomponent;
		private var _scrollToPoint		: Point;
		
		public function uiff_frame(parent:uif_component, ax:int=0, ay:int=0, awidth:int=0, aheight:int=0, styleClass: Object='') {
			super(parent, ax, ay, awidth, aheight, styleClass);
			createComponents();
		}
		
		override protected function listenEvents():void {
			super.listenEvents();
			addEvent(MouseEvent.MOUSE_MOVE, doMouseMove);
			addEvent(MouseEvent.MOUSE_DOWN, doMouseDown);
			addEvent(MouseEvent.MOUSE_UP, doMouseUp, app);
			addEvent(MouseEvent.ROLL_OUT, doMouseOut);
			addEvent(Event.ENTER_FRAME, doFrame);
		}
		
		protected function createComponents(): void {
			var _rect: Rectangle = maskBounds;
			_buttonsLayer = new uif_ecomponent(this, 0, 0, width, height);
			_area = new uiff_area(this, _rect.x, _rect.y, _rect.width, _rect.height, style.area);
			_area.index = 0;
			_area.addEvent(uif_component.RESIZE, doAreaResize);
			createArrows();
		}
		
		protected function createArrows(): void {
			var _bwidth: Number = sizeActiveRegion;
			var _bheight: Number = sizeActiveRegion * 0.5;
			var rect: Rectangle = getInner();
			_buttons = [
				new uif_arrowbutton(_buttonsLayer, rect.x + (rect.width - _bwidth) / 2, rect.y , _bwidth, _bheight, uif_draw.TOP, style.arrows),
				new uif_arrowbutton(_buttonsLayer, rect.x + (rect.width - _bheight), rect.y + (rect.height - _bwidth) / 2, _bheight, _bwidth, uif_draw.RIGHT, style.arrows),
				new uif_arrowbutton(_buttonsLayer, rect.x + (rect.width - _bwidth) / 2, rect.y + rect.height - _bheight, _bwidth, _bheight, uif_draw.BOTTOM, style.arrows),
				new uif_arrowbutton(_buttonsLayer, rect.x, rect.y + (rect.height - _bwidth) / 2, _bheight, _bwidth, uif_draw.LEFT, style.arrows)
			];
			
			_buttons[0].setVisibility(false);
			_buttons[1].setVisibility(false);
			_buttons[2].setVisibility(false);
			_buttons[3].setVisibility(false);
		}
		
		protected function doAreaResize(e: Event): void {
			updateArrowVisible();
		}
		
		public function get scrollingTotal(): Point {
			var mb: Rectangle = maskBounds;
			return new Point(area.width - mb.width, area.height - mb.height); 
		}
		
		public function get scrollingValue(): Point {
			return area.position.subtract(maskBounds.topLeft); 
		}
		
		public function set scrollingValue(a_value: Point): void {
			area.position = a_value.add(maskBounds.topLeft);
		}
		
		protected function updateArrowVisible(): void {
			var aRect: Rectangle = area.getOuter();
			var iRect: Rectangle = getInner();
			
			_buttons[0].setVisibility(aRect.y < iRect.y);
			_buttons[1].setVisibility(aRect.right > iRect.right);
			_buttons[2].setVisibility(aRect.bottom > iRect.bottom);
			_buttons[3].setVisibility(aRect.x < iRect.x);
		}
		
		public function get area(): uiff_area {
			return _area;
		}
		
		private function doMouseMove(e: MouseEvent): void {
			if (!e.buttonDown) _sr = scrollRegion(mouseX, mouseY);
		}
		
		private function doMouseDown(e: MouseEvent): void {
			_mousePrev 	= mousePos;
			_buttonDown	= true;
		}
		
		private function doMouseUp(e: MouseEvent): void {
			_buttonDown	= false;
		}
		
		private function doMouseOut(e: Event): void {
			if (_sr && (!_inertia || !_inertia.length)) _inertia = _sr.clone();
			_sr = null;
		}
		
		protected function abilityToMove(rmove: Point): Point {
			var rect	: Rectangle = maskBounds;
			var result	: Point 	= new Point();
			if ((rmove.x > 0) && (rect.x > _area.x)) {
				if (_area.x + rmove.x > rect.x)
					result.x = rect.x - _area.x;
				else result.x = rmove.x;
			} else if ((rmove.x < 0) && (rect.right < _area.right)) {
				if (_area.right + rmove.x < rect.right)
					result.x = rect.right - _area.right;
				else result.x = rmove.x;
			}
			return result;
		}
		
		protected function scrollTo(pAdd: Point): void {
			var move: Point = abilityToMove(pAdd);
			if (move.x || move.y) {
				_area.x += move.x;
				_area.y += move.y;
				updateArrowVisible();
			}
		}
		
		public function scrollToItem(item: uif_component): void {
			if (item) {
				var r: Rectangle = item.getOuter();
				var mbounds: Rectangle = maskBounds;
				r.x -= mbounds.x;
				r.y -= mbounds.y;
				if (!mbounds.intersects(r)) {
					_scrollToPoint = new Point(-r.x, -r.y);
					_buttonDown = false;
				}
			}
//			_scrollToChild = item.getOuter();
		}
		
		private function doFrame(e: Event): void {
			if (_scrollToPoint) {
				var p: Point = new Point((_scrollToPoint.x - area.x) / 5, (_scrollToPoint.y - area.y) / 5);
				if (p.length > 0.1) scrollTo(p);
				else _scrollToPoint = null;
			} else {
				if (_buttonDown) {
					_inertia = mousePos.subtract(_mousePrev);
					_mousePrev = mousePos;
				}
				
				if (_inertia && (_inertia.length > 0.1)) {
					scrollTo(_inertia);
					_inertia.x *= 0.85;
					_inertia.y *= 0.85;
				} else {
					if (_inertia) _inertia = new Point();
					if (_sr && (_sr.length > 0)) scrollTo(_sr);
				}
			}
		}
		
		protected function getSpeed(xAxis: Boolean = true): Number {
			var mb: Rectangle = maskBounds;
			var aSpeed: Number = 20;
			var p: String = xAxis?'width':'height';
			var result: Number = (1 - Math.min(mb[p] / _area[p], 1)) * aSpeed + 1;
			return result;
		}
		
		protected function get quietRegion(): Rectangle {
			var sizeRegion: Number = sizeActiveRegion;
			var rect: Rectangle = new Rectangle(0, 0, width, height);
			rect.inflate(-sizeRegion, -sizeRegion);
			return rect;
		}
		
		protected function get sizeActiveRegion(): Number {
			return Math.min(height / 3, width / 3);
		}
		
		private function scrollRegion(a_x: Number, a_y: Number): Point {
			var result: Point = new Point();
			var sizeRegion: Number 	= sizeActiveRegion;
			var rect: Rectangle 	= quietRegion;
			if (a_x < rect.x) result.x = (rect.x - a_x) / sizeRegion * getSpeed();
			else if (a_x > rect.right) result.x = (rect.right - a_x) / sizeRegion * getSpeed();
			if (a_y < rect.y) result.y = (rect.y - a_y) / sizeRegion * getSpeed(true);
			else if (a_y > rect.bottom) result.y = (rect.bottom - a_y) / sizeRegion * getSpeed(true);
			return result;
		}
	}
}